﻿using System.Collections.Generic;

namespace Calculator
{
    public class SymbolHandler :ISymbolHandler
    {
        private readonly IOperatorHandler operatorHandler;

        public SymbolHandler(IOperatorHandler operatorHandlerParam)
        {
            operatorHandler = operatorHandlerParam;
        }

        public string PopWholeStackToResult(string resultString, Stack<char> operatorStack)
        {
            while (operatorStack.Count > 0)
            {
                resultString += operatorStack.Pop() + "|";
            }
            return resultString;
        }

        private string OperatorHandle(string resultString, string operatorParam, Stack<char> operatorStack)
        {
            while (operatorStack.Count > 0 && operatorHandler.IsOperator(operatorStack.Peek()) &&
                   operatorHandler.GetPrecedence(operatorParam) <= operatorHandler.GetPrecedence(operatorStack.Peek()))
            {
                resultString += operatorStack.Pop() + "|";
            }
            operatorStack.Push(operatorParam.ToCharArray()[0]);
            return resultString;
        }

        public string SymbolHandle(Stack<char> operatorStack, string resultString, string piece)
        {
            if (operatorHandler.IsNumber(piece))
            {
                resultString += piece + "|";
            }
            else if (operatorHandler.IsOperator(piece))
            {
                resultString = OperatorHandle(resultString, piece, operatorStack);
            }
            else if (piece == "(")
            {
                operatorStack.Push('(');
            }
            else if (piece == ")")
            {
                resultString = ClosingParenthesHandle(resultString, operatorStack);
            }

            return resultString;
        }

        private string ClosingParenthesHandle(string resultString, Stack<char> operatorStack)
        {
            char myOperator;
            while ((myOperator = operatorStack.Pop()) != '(')
            {
                resultString += myOperator + "|";
            }
            if (operatorStack.Count > 0 && operatorHandler.IsOperator(operatorStack.Peek()))
            {
                resultString += operatorStack.Pop() + "|";
            }

            return resultString;
        }

        public void ComputeOperationOnStack(char operation, Stack<int> numberStack)
        {
            switch (operation)
            {
                case '+':
                    numberStack.Push(numberStack.Pop() + numberStack.Pop());
                    break;
                case '-':
                    numberStack.Push(-numberStack.Pop() + numberStack.Pop());
                    break;
                case '*':
                    numberStack.Push(numberStack.Pop() * numberStack.Pop());
                    break;
                case '/':
                    {
                        int divisor = numberStack.Pop();
                        int dividend = numberStack.Pop();
                        numberStack.Push(dividend / divisor);
                    }
                    break;
            }
        }
    }
}